home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 June: ROMin Holiday / ADC Developer CD (1992-06) (''ROMin Holiday'')_iso / Developer Connection - 06-1992.iso / Developer Essentials / DTS Sample Code / System 7.0 Samples / MacShell / AEConnect.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-04  |  16.0 KB  |  568 lines  |  [TEXT/MPS ]

  1. /*
  2. ** Apple Macintosh Developer Technical Support
  3. **
  4. ** Program:        MacShell
  5. ** File:        AEConnect.c
  6. ** Written by:  Eric Soldan
  7. **
  8. ** Copyright © 1990-1991 Apple Computer, Inc.
  9. ** All rights reserved.
  10. **
  11. ** This is the custom AppleEvents code used for establishing a connection
  12. ** to another window.  MacShell targets a specific window in an application,
  13. ** not just an application.  It also sends and returns more information
  14. ** about the connection, such as user name, zone, and machine.  This
  15. ** information is two-way, so each user can know who they are connected to.
  16. */
  17.  
  18.  
  19.  
  20. /*****************************************************************************/
  21.  
  22.  
  23.  
  24. #include "MacShell.h"            /* Get the MacShell includes/typedefs, etc.    */
  25. #include "MacShellCommon.h"        /* Get the stuff in common with rez.        */
  26. #include "MacShell.protos"        /* Get the prototypes for MacShell.            */
  27.  
  28. #ifndef __RESOURCES__
  29. #include <Resources.h>
  30. #endif
  31.  
  32. #ifndef THINK_C
  33. #ifndef __SYSEQU__
  34. #include <SysEqu.h>
  35. #endif
  36. #endif
  37.  
  38. #ifndef __TOOLUTILS__
  39. #include <ToolUtils.h>
  40. #endif
  41.  
  42. #ifdef THINK_C
  43. #include "Utilities.h"
  44. #else
  45. #ifndef __UTILITIES__
  46. #include <Utilities.h>
  47. #endif
  48. #endif
  49.  
  50.  
  51.  
  52. /*****************************************************************************/
  53.  
  54.  
  55.  
  56. extern Boolean        gHasAppleEvents;
  57. extern Cursor        *gCursorPtr;
  58.  
  59. static pascal OSErr        DoAEAnswer(AppleEvent *message, AppleEvent *reply, long refcon);
  60. static pascal OSErr        ReceiveConnect(AppleEvent *message, AppleEvent *reply, long refcon);
  61. static pascal OSErr        ReceiveConnectReply(AppleEvent *message, AppleEvent *reply);
  62. static pascal Boolean    AEPortFilter(LocationNamePtr locationName, PortInfoPtr thePortInfo);
  63.  
  64.  
  65.  
  66. /*****************************************************************************/
  67.  
  68.  
  69.  
  70. static triplets keywordsToInstall[] = {
  71.     { kCoreEventClass,        kAEAnswer,            (ProcPtr)DoAEAnswer },
  72.     { kCustomEventClass,    keyAppConnect,        (ProcPtr)ReceiveConnect },
  73. };        /* These are the custom AppleEvents. */
  74.  
  75.  
  76.  
  77. /*****************************************************************************/
  78. /*****************************************************************************/
  79.  
  80.  
  81.  
  82. /* InitConnectAppleEvents
  83. **
  84. ** Install the AppleEvents we use to establish a connection to a specific
  85. ** window.  This is done in addition to installing the required AppleEvents.
  86. ** InitAppleEvents, which installs the required AppleEvents, must be called
  87. ** first, since it sets up some global values.
  88. */
  89.  
  90. #pragma segment AppleEvents
  91. void    InitConnectAppleEvents(void)
  92. {
  93.     OSErr    err;
  94.     short    i;
  95.  
  96.     if (gHasAppleEvents) {
  97.         for (i = 0; i < (sizeof(keywordsToInstall) / sizeof(triplets)); ++i) {
  98.             err = AEInstallEventHandler(
  99.                 keywordsToInstall[i].theEventClass,    /* What class to install.  */
  100.                 keywordsToInstall[i].theEventID,    /* Keywords to install.    */
  101.                 keywordsToInstall[i].theHandler,    /* The AppleEvent handler. */
  102.                 0L,                                    /* Unused refcon.           */
  103.                 false                                /* Only for our app.       */
  104.             );
  105.  
  106.             if (err) {
  107.                 Alert(rErrorAlert, (ModalFilterProcPtr)alertFilter);
  108.                 return;
  109.             }
  110.         }
  111.     }
  112. }
  113.  
  114.  
  115.  
  116. /*****************************************************************************/
  117.  
  118.  
  119.  
  120. #pragma segment AppleEvents
  121. pascal OSErr    DoAEAnswer(AppleEvent *message, AppleEvent *reply, long refcon)
  122. {
  123. #pragma unused (refcon)
  124.  
  125.     OSErr    err;
  126.  
  127.     gCursorPtr = nil;
  128.         /* Force re-calc of cursor region and cursor to use. */
  129.  
  130.     err = ReceiveConnectReply(message, reply);
  131.  
  132.     AEPutParamPtr(                /* RETURN REPLY ERROR, EVEN IF NONE... */
  133.         reply,                    /* The AppleEvent.              */
  134.         keyReplyErr,            /* AEKeyword                 */
  135.         typeShortInteger,        /* Desired type.             */
  136.         (Ptr)&err,                /* Pointer to area for data. */ 
  137.         sizeof(short)            /* Size of data area.         */
  138.     );
  139.  
  140.     return(noErr);
  141. }
  142.  
  143.  
  144.  
  145. /*****************************************************************************/
  146.  
  147.  
  148.  
  149. /* SendConnect
  150. **
  151. */
  152.  
  153. #pragma segment AppleEvents
  154. OSErr    SendConnect(FileRecHndl frHndl)
  155. {
  156.     AEAddressDesc    remoteLoc;
  157.     OSErr            err;
  158.     long            windID[2], size;
  159.     char            hstate;
  160.     Ptr                ptr1, ptr2;
  161.     AppleEvent        theAevt, reply;
  162.     Str255            macText, appText;
  163.     Str32            remoteName;
  164.     Handle            remoteNameHndl;
  165.     FSSpec            myFSS;
  166.     short            i;
  167.  
  168.     theAevt.dataHandle = reply.dataHandle = nil;
  169.         /* Make sure disposing of the descriptors is okay in all cases.
  170.         ** This will not be necessary after 7.0b3, since the calls that
  171.         ** attempt to create the descriptors will nil automatically
  172.         ** upon failure. */
  173.  
  174.     err = noErr;
  175.         /* We may not make the first operation that can cause an error,
  176.         ** so we have to initialize err. */
  177.  
  178.     remoteLoc.dataHandle = nil;
  179.         /* Make it safe to dispose of in all cases. */
  180.  
  181.     GetIndString(macText, rPPCText, sTitleText);
  182.     GetIndString(appText, rPPCText, sAppText);
  183.     err = MakeTarget(&remoteLoc, false, kAEWaitReply,
  184.         macText, appText, (PPCFilterProcPtr)AEPortFilter, (char *)"\pMacShell");
  185.             /* Generate the target for the remote user. */
  186.     (*frHndl)->connect.windowID[0] = windID[0] = (TickCount() & 0xFFFFFFFE);
  187.     (*frHndl)->connect.windowID[1] = windID[0];
  188.     (*frHndl)->connect.remoteLoc   = remoteLoc;
  189.  
  190.     if (!err) {        /* Create the AppleEvent... */
  191.         err = AECreateAppleEvent(        /* CREATE EMPTY APPLEEVENT.     */
  192.             kCustomEventClass,            /* Event class.                 */
  193.             typeAppConnect,                /* Event ID.                 */
  194.             &remoteLoc,                    /* Address of receiving app. */
  195.             kAutoGenerateReturnID,        /* This value causes the     */
  196.                                         /* AppleEvent manager to     */
  197.                                         /* assign a return ID that     */
  198.                                         /* is unique to the session. */
  199.             kAnyTransactionID,            /* Ignore transaction ID.     */
  200.             &theAevt                    /* Location of event.         */
  201.         );
  202.     }
  203.  
  204.     if (!err) {        /* If we have an empty list to add to... */
  205.         hstate = LockHandleHigh((Handle)frHndl);
  206.         ptr1   = (Ptr)&((*frHndl)->connect);
  207.         ptr2   = (Ptr)&((*frHndl)->connect.endSendInfo);
  208.         size   = (long)ptr2 - (long)ptr1;
  209.         err = AEPutParamPtr(    /* ADD FILE INFO TO THE APPLEEVENT. */
  210.             &theAevt,            /* AppleEvent to add to.           */
  211.             keyAppConnect,        /* AEKeyword.                       */
  212.             typeAppConnect,        /* Desired type.                   */
  213.             ptr1,                /* Pointer to the data to be sent. */
  214.             size                /* Size of the data to be sent.       */
  215.         );
  216.         HSetState((Handle)frHndl, hstate);
  217.     }
  218.  
  219.     if (!err) {
  220.         myFSS = (*frHndl)->fileState.fss;
  221.         err = AEPutParamPtr(    /* ADD WINDOW NAME TO APPLEEVENT. */
  222.             &theAevt,            /* AppleEvent to add to. */
  223.             keyFSS,                /* AEKeyword.             */
  224.             typeFSS,            /* Desired type.         */
  225.             (Ptr)&myFSS,        /* Pointer to the data.     */
  226.             sizeof(FSSpec)        /* Size of the data.     */
  227.         );
  228.     }
  229.  
  230.     if (!err) {
  231.         remoteName[0] = 0;
  232.         if (remoteNameHndl = GetResource('STR ', -16096))
  233.             pstrcpy((char *)remoteName, (char *)(*remoteNameHndl));
  234.         err = AEPutParamPtr(    /* ADD USER NAME TO APPLEEVENT. */
  235.             &theAevt,            /* AppleEvent to add to. */
  236.             keyPascal,            /* AEKeyword.             */
  237.             typePascal,            /* Desired type.         */
  238.             (Ptr)remoteName,    /* Pointer to the data.     */
  239.             remoteName[0] + 1    /* Size of the data.     */
  240.         );
  241.     }
  242.  
  243.     if (!err) {        /* If we have an AppleEvent ready to send... */
  244.         err = AESend(            /* SEND APPLEEVENT.                */
  245.             &theAevt,            /* Our Apple Event to send.        */
  246.             &reply,                /* We may have a reply.            */
  247.             kAEQueueReply,        /* Type of reply.                */
  248.             kAENormalPriority,    /* App. send priority.            */
  249.             0,                    /* We aren't waiting.            */
  250.             nil,                /* We aren't waiting.            */
  251.             nil                    /* EventFilterProcPtr.            */
  252.         );
  253.     }
  254.     if (remoteLoc.descriptorType == typeProcessSerialNumber)
  255.         err = ReceiveConnectReply(&reply, &reply);
  256.             /* If we want a queue reply, and if we are sending to ourselves,
  257.             ** then we already have the reply.  Since we are sending to
  258.             ** ourselves, we don't have to wait for an event.  Stuff happens
  259.             ** right away.  We're (probably) happy. */
  260.  
  261.     AEDisposeDesc(&theAevt);
  262.     AEDisposeDesc(&reply);
  263.         /* Dispose of the descriptors, created or not.
  264.         ** If not created, no harm done by calling. */
  265.  
  266.     if (err) {
  267.         AEDisposeDesc(&remoteLoc);
  268.             /* If we didn't connect, get rid of the target descriptor. */
  269.  
  270.         for (i = 0; i < 2; ++i) (*frHndl)->connect.windowID[i] = 0;
  271.             /* Mark this window so that it will never be found if we somehow
  272.             ** do get an answer from the receiver, even after failure. */
  273.     }
  274.  
  275.     return(err);
  276. }
  277.  
  278.  
  279.  
  280. /*****************************************************************************/
  281.  
  282.  
  283.  
  284. /* ReceiveConnect
  285. **
  286. */
  287.  
  288. #pragma segment AppleEvents
  289. pascal OSErr    ReceiveConnect(AppleEvent *message, AppleEvent *reply, long refcon)
  290. {
  291. #pragma unused (refcon)
  292.  
  293.     OSErr            err;
  294.     FileRecHndl        frHndl;
  295.     char            hstate;
  296.     Ptr                ptr1, ptr2;
  297.     long            size, windID[2];
  298.     AEAddressDesc    senderTarget;
  299.     DescType        ignoredType;
  300.     Size            ignoredSize;
  301.     FSSpec            myFSS;
  302.     Str32            remoteZone, remoteMachine, remoteApplication;
  303.     char            remoteName[33];
  304.     Handle            remoteNameHndl;
  305.  
  306.     err = noErr;
  307.     AEPutParamPtr(                /* RETURN REPLY ERROR, EVEN IF NONE... */
  308.         reply,                    /* The AppleEvent.              */
  309.         keyReplyErr,            /* AEKeyword                 */
  310.         typeShortInteger,        /* Desired type.             */
  311.         (Ptr)&err,                /* Pointer to area for data. */ 
  312.         sizeof(short)            /* Size of data area.         */
  313.     );
  314.  
  315.     IncNewFileNum(false);
  316.     err = AppNewDocument(&frHndl, docFileType);
  317.     IncNewFileNum(true);
  318.  
  319.     if (err) return(err);
  320.  
  321.     if (!err) {
  322.         hstate = LockHandleHigh((Handle)frHndl);
  323.         ptr1   = (Ptr)&((*frHndl)->connect);
  324.         ptr2   = (Ptr)&((*frHndl)->connect.endSendInfo);
  325.         size   = (long)ptr2 - (long)ptr1;
  326.         err = AEGetParamPtr(    /* GET CONNECT INFO FROM THE APPLEEVENT. */
  327.             message,            /* The AppleEvent.              */
  328.             keyAppConnect,        /* AEKeyword                 */
  329.             typeAppConnect,        /* Desired type.             */
  330.             &ignoredType,        /* Type code.                 */
  331.             ptr1,                /* Pointer to area for data. */ 
  332.             size,                /* Size of data area.         */
  333.             &ignoredSize        /* Returned size of data.     */
  334.         );
  335.         HSetState((Handle)frHndl, hstate);
  336.     }
  337.  
  338.     if (!err) {
  339.         err = AEGetAttributeDesc(    /* GET ADDRESS OF SENDER.     */
  340.             message,                /* Get address of sender from message.         */
  341.             keyAddressAttr,            /* We want an address.                         */
  342.             typeWildCard,            /* We want the address of the sender.         */
  343.             &senderTarget            /* Address of sender.                         */
  344.         );
  345.         if (!err) {
  346.             (*frHndl)->connect.remoteLoc = senderTarget;
  347.             err = AEGetParamPtr(    /* GET FSSpec (FOR WINDOW NAME) FROM APPLEEVENT. */
  348.                 message,            /* The AppleEvent.              */
  349.                 keyFSS,                /* AEKeyword                 */
  350.                 typeFSS,            /* Desired type.             */
  351.                 &ignoredType,        /* Type code.                 */
  352.                 (Ptr)&myFSS,        /* Pointer to area for data. */ 
  353.                 sizeof(FSSpec),        /* Size of the data.         */
  354.                 &ignoredSize        /* Returned size of data.     */
  355.             );
  356.             if (!err)
  357.                 pstrcpy((char *)(*frHndl)->fileState.fss.name, (char *)myFSS.name);
  358.         }
  359.         if (!err) {
  360.             err = AEGetParamPtr(    /* GET USER NAME FROM APPLEEVENT. */
  361.                 message,            /* The AppleEvent.              */
  362.                 keyPascal,            /* AEKeyword                 */
  363.                 typePascal,            /* Desired type.             */
  364.                 &ignoredType,        /* Type code.                 */
  365.                 remoteName,            /* Pointer to area for data. */ 
  366.                 sizeof(Str255),        /* Size of the data.         */
  367.                 &ignoredSize        /* Returned size of data.     */
  368.             );
  369.             (*frHndl)->connect.remoteName[0] = 0;
  370.             if (!err) {
  371.                 pstrcpy((char *)(*frHndl)->connect.remoteName, (char *)remoteName);
  372.                 remoteZone[0] = remoteMachine[0] = 0;
  373.                 GetTargetInfo(senderTarget, remoteZone, remoteMachine, remoteApplication);
  374.                 pstrcpy((char *)&(*frHndl)->connect.remoteZone[0], (char *)remoteZone);
  375.                 pstrcpy((char *)&(*frHndl)->connect.remoteMachine[0], (char *)remoteMachine);
  376.             }
  377.         }
  378.     }
  379.  
  380.     if (!err) {        /* If we got the remote user address... */
  381.  
  382.         (*frHndl)->connect.windowID[0] = windID[0] = (TickCount() | 0x01);
  383.         (*frHndl)->connect.connected = true;
  384.  
  385.         if ((*frHndl)->doc.version != kVersion) err = errAEWrongDataType;
  386.             /* Incompatible file format. */
  387.  
  388.         if (!err) {
  389.             windID[1] = (*frHndl)->connect.windowID[1];
  390.             err = AEPutParamPtr(    /* RETURN RECEIVER WINDOW ID. */
  391.                 reply,                /* The AppleEvent.              */
  392.                 keyWindowID,        /* AEKeyword                 */
  393.                 typeDoubleLong,        /* Type code.                 */
  394.                 (Ptr)&windID[0],    /* Pointer to area for data. */ 
  395.                 2 * sizeof(long)    /* Size of data area.         */
  396.             );
  397.         }
  398.  
  399.         if (!err) {
  400.             remoteName[0] = 0;
  401.             if (remoteNameHndl = GetResource('STR ', -16096))
  402.                 pstrcpy((char *)remoteName, (char *)(*remoteNameHndl));
  403.             err = AEPutParamPtr(    /* RETURN RECEIVER USER NAME. */
  404.                 reply,                /* The AppleEvent.              */
  405.                 keyPascal,            /* AEKeyword                 */
  406.                 typePascal,            /* Type code.                 */
  407.                 remoteName,            /* Pointer to area for data. */ 
  408.                 remoteName[0] + 1    /* Size of data area.         */
  409.             );
  410.         }
  411.  
  412.         if (!err) err = DoNewWindow(frHndl, nil, (WindowPtr)-1, kwAppWindow);
  413.             /* If connecting worked, create a window for the document. */
  414.     }
  415.  
  416.     if (err) AppDisposeDocument(frHndl);
  417.  
  418.     if (!err) NotifyUser();
  419.     return(err);
  420. }
  421.  
  422.  
  423.  
  424. /*****************************************************************************/
  425.  
  426.  
  427.  
  428. #pragma segment AppleEvents
  429. pascal OSErr    ReceiveConnectReply(AppleEvent *message, AppleEvent *reply)
  430. {
  431. #pragma unused (reply)
  432.  
  433.     OSErr            err, replyErr;
  434.     DescType        actualType;
  435.     long            windID[2], actualSize;
  436.     WindowPtr        window;
  437.     FileRecHndl        frHndl;
  438.     Str32            remoteZone, remoteMachine, remoteApplication;
  439.     char            remoteName[33];
  440.  
  441.     err = AEGetParamPtr(        /* CHECK FOR A RECEIVER ERROR... */
  442.         message,                /* The AppleEvent.              */
  443.         keyReplyErr,            /* AEKeyword                 */
  444.         typeShortInteger,        /* Desired type.             */
  445.         &actualType,            /* Type code.                 */
  446.         (Ptr)&replyErr,            /* Pointer to area for data. */ 
  447.         sizeof(short),            /* Size of data area.         */
  448.         &actualSize                /* Returned size of data.     */
  449.     );
  450.     if (!err) err = replyErr;
  451.  
  452.     if (!err) {
  453.         err = AEGetParamPtr(    /* GET RECEIVER WINDOW ID. */
  454.             message,            /* The AppleEvent.              */
  455.             keyWindowID,        /* AEKeyword                 */
  456.             typeDoubleLong,        /* Desired type.             */
  457.             &actualType,        /* Type code.                 */
  458.             (Ptr)&windID[0],    /* Pointer to area for data. */ 
  459.             2 * sizeof(long),    /* Size of data area.         */
  460.             &actualSize            /* Returned size of data.     */
  461.         );
  462.     }
  463.  
  464.     if (!err) {        /* If we got the receiver window ID... */
  465.  
  466.         window = GetAEWindow(windID[1], windID[1]);
  467.             /* The ID's are still both ours, since this is where we
  468.             ** get the receiver's ID returned.  windID[0] holds the
  469.             ** receiver's ID, and windID[1] holds ours. */
  470.  
  471.         if (window) {
  472.             frHndl = (FileRecHndl)GetWRefCon(window);
  473.             if (!(*frHndl)->connect.connected) {
  474.                 err = AEGetParamPtr(
  475.                     message,            /* The AppleEvent.              */
  476.                     keyPascal,            /* AEKeyword                 */
  477.                     typePascal,            /* Desired type.             */
  478.                     &actualType,        /* Type code.                 */
  479.                     remoteName,            /* Pointer to area for data. */ 
  480.                     sizeof(Str255),        /* Size of data area.         */
  481.                     &actualSize            /* Returned size of data.     */
  482.                 );
  483.  
  484.                 (*frHndl)->connect.remoteName[0] = 0;
  485.                 if (!err) {
  486.                     (*frHndl)->connect.windowID[1] = windID[0];
  487.                     pstrcpy((char *)&(*frHndl)->connect.remoteName[0], (char *)remoteName);
  488.                     GetTargetInfo((*frHndl)->connect.remoteLoc,
  489.                                   remoteZone, remoteMachine, remoteApplication);
  490.                     pstrcpy((char *)&(*frHndl)->connect.remoteZone[0], (char *)remoteZone);
  491.                     pstrcpy((char *)&(*frHndl)->connect.remoteMachine[0], (char *)remoteMachine);
  492.                     (*frHndl)->connect.connected = true;
  493.                 }
  494.                 else
  495.                     (*frHndl)->connect.windowID[0] = (*frHndl)->connect.windowID[1] = 0;
  496.             }
  497.         }
  498.     }
  499.  
  500.     return(err);
  501. }
  502.  
  503.  
  504.  
  505. /*****************************************************************************/
  506.  
  507.  
  508.  
  509. /* GetAEWindow
  510. **
  511. ** Find the window with the specified window ID's.
  512. */
  513.  
  514. #pragma segment AppleEvents
  515. WindowPtr    GetAEWindow(long windID_0, long windID_1)
  516. {
  517.     WindowPeek    window;
  518.     FileRecHndl    frHndl;
  519.  
  520. #ifdef __SYSEQU__
  521.     for (window = *(WindowPeek *)WindowList; window; window = window->nextWindow) {
  522. #else
  523.     for (window = (WindowPeek)WindowList; window; window = window->nextWindow) {
  524. #endif
  525.         if (IsAppWindow((WindowPtr)window)) {
  526.             frHndl = (FileRecHndl)GetWRefCon((WindowPtr)window);
  527.             if (
  528.                 ((*frHndl)->connect.windowID[0] == windID_0) &&
  529.                 ((*frHndl)->connect.windowID[1] == windID_1)
  530.             ) return((WindowPtr)window);
  531.         }
  532.     }
  533.  
  534.     return(nil);
  535. }
  536.  
  537.  
  538.  
  539. /*****************************************************************************/
  540.  
  541.  
  542.  
  543. /* AEPortFilter
  544. **
  545. ** Don't allow PPCBrowser to show any applications other than MacShell.
  546. */
  547.  
  548. #pragma segment AppleEvents
  549. pascal Boolean    AEPortFilter(LocationNamePtr locationName, PortInfoPtr thePortInfo)
  550. {
  551. #pragma unused (locationName)
  552.  
  553.     long    type;
  554.  
  555.     if (thePortInfo->name.portKindSelector == ppcByString) {
  556.         BlockMove(thePortInfo->name.u.portTypeStr + 1, (Ptr)&type, 4);
  557.             /* The BlockMove is so that we don't get an address error
  558.             ** on a 68000-based machine due to referencing a long at
  559.             ** an odd-address. */
  560.         if (type == docCreator) return(true);
  561.     }
  562.  
  563.     return(false);
  564. }
  565.  
  566.  
  567.  
  568.